package engine.scheduler.jobs;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;

import engine.Consts;
import engine.dataobjects.MailItem;
import engine.services.IDataResource;

/***
 * Job that runs to update the configuration data in case
 * changes have been made to the xml file
 * 
 * @author IlanaP
 *
 */
public class ConfigurationUpdateJob extends QuartzJobBean {

	IDataResource configResource;

	private static Log log = LogFactory.getLog(ConfigurationUpdateJob.class);

	
	public void setConfigResource(IDataResource configResource) {
		this.configResource = configResource;
	}
	
	private ApplicationContext getContext() {
		ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/applicationContext.xml");
		return context;
	}

	@Override
	public void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
		log.info("executing ConfigurationUpdateJob");
		try {
			// pause the scheduler
			log.info("Pausing scheduler");
			Scheduler scheduler = arg0.getScheduler();
			scheduler.pauseJobGroup(Consts.MESSAGE_JOB_GROUP);
			
			// get all the running jobs
			String[] jobNames = scheduler.getJobNames(Consts.MESSAGE_JOB_GROUP);
			List<String> jobNamesList = new ArrayList<String>();
			for (String name : jobNames) {
				jobNamesList.add(name);
			}

			// get all the mail items
			configResource.init();
			List<MailItem> items = configResource.getMailItems();
			ApplicationContext context = getContext();
			for (MailItem item : items) {
				if (!jobNamesList.contains(item.getId())) {
					log.info("New job Id: " + item);
					// job is a new job and will create it here

					IMailItemJob job = (IMailItemJob)context.getBean("mailItemJob");
					IMailItemJobDetail jobDetails = (IMailItemJobDetail)context.getBean("mailItemJobDetail");
					// setting up the new item
					jobDetails.setItem(item);
					// adding it to the queue
					job.init(jobDetails, false);
				} else {
					// checking exising job has not changed
					log.info("Checking existing job Id: " + item);
					
					IMailItemJobDetail details = (IMailItemJobDetail)scheduler.getJobDetail(item.getId(), Consts.MESSAGE_JOB_GROUP);
					// updating in case it has changed
					if (details.getItem().equals(item)) {
						log.info("No changes for job");						
					} else {
						log.info("Job has changed. we will remove it and recreate it");						
						// removing and recreating the items
						jobNamesList.remove(item.getId());
						IMailItemJob job = (IMailItemJob)context.getBean("mailItemJob");
						IMailItemJobDetail jobDetails = (IMailItemJobDetail)context.getBean("mailItemJobDetail");
						jobDetails.setItem(item);
						job.init(jobDetails, false);
					}
					
					// worked on this one, can be removed from the list of jobs
					jobNamesList.remove(item.getId());
				}
			}

			// these jobs have been removed and we will remove them from the scheduler
			for (String jobNameForDelete : jobNamesList) {
				IMailItemJobDetail details = (IMailItemJobDetail)scheduler.getJobDetail(jobNameForDelete, Consts.MESSAGE_JOB_GROUP);
				log.info("Removing job that is not active or existing anymore. Id: " + details.getItem().getName());
				scheduler.removeJobListener(jobNameForDelete);
			}
			
			// restart the scheduler
			log.info("Resuming scheduler");
			scheduler.resumeJobGroup(Consts.MESSAGE_JOB_GROUP);

		} catch (Exception e) {
			log.error(e);
		}
		log.info("done executing ConfigurationUpdateJob");
		
		log.info("next run is at: " + arg0.getNextFireTime());							
	}

}
